﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Collections;
using System.Text.RegularExpressions;
using System.Security.Policy;
using System.Threading;
using Common;

namespace HttpHelper
{
    public class HttpDownloader
    {
        public static object lockobject = new object();
        public static Hashtable DnsLookup;
        public const int XML_TIMEOUT = 2500;
        public static string DownloadPage(Uri uri)
        {
            return DownloadPage(uri, null);
        }
        public static string DownloadPage(Uri uri, string encoding)
        {
            return DownloadPage(uri, encoding, false, false); 
        }
        
		public static string DownloadPage(Uri uri, string encoding, bool isXml, bool checkModified)
		{
			string page;
            string etag = string.Empty;
            try
            {
                HttpWebRequest request = MakeRequestObject(uri);
                //Dal.DatabaseAbstractionLayer dal = new Dal.DatabaseAbstractionLayer("");

                if (checkModified)
                {
                    //request.IfModifiedSince = dal.GetLastDownloadDate(uri);
                    //request.Headers[HttpRequestHeader.IfNoneMatch] = dal.GetEtag(uri);
                }
                //else
                //    request.IfModifiedSince = DateTime.MinValue;

               
                using (HttpWebResponse res = (HttpWebResponse)request.GetResponse())
                {
                    if (res.StatusCode == HttpStatusCode.NotModified)
                        throw new WebException("Content Not Modified");
                    Stream responseStream = res.GetResponseStream();
                    if (res.ContentEncoding.ToLower().Contains("gzip"))
                        responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
                    else if (res.ContentEncoding.ToLower().Contains("deflate"))
                        responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);

                    var enc = (encoding == null) ? Encoding.GetEncoding(res.CharacterSet) : Encoding.GetEncoding(encoding);
                    //var enc = Encoding.GetEncoding(res.CharacterSet);
                    var s = new StreamReader(new TimeoutStream(responseStream, 10000), enc);
                    page = s.ReadToEnd();
                    //etag = res.Headers[HttpResponseHeader.ETag];
                    res.Close();
                    s.Close();
                    //dal.SetUrlData(uri, DateTime.Now, isXml, etag);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("DownloadPage Error : "  + uri.ToString() + " , " + e.Message);
                throw e;
            }

            
			return page;
		}
		public static string DownloadPage(Uri uri, int MaxRetries)
		{
			if (MaxRetries < 0) return string.Empty;
			int i = 0;

			while (true)
			{
				try
				{
					return DownloadPage(uri);
				}
				catch (Exception ex)
				{
					Console.WriteLine(uri.ToString() + " " + ex.Message);
					if (i < MaxRetries) { i++; continue; }
					throw ex;
				}
			}			
		}
        
        public static bool isXML(Uri uri)
        {
            HttpWebRequest request = MakeRequestObject(uri);
            request.Method = "HEAD";
            request.Timeout = XML_TIMEOUT;
            request.ReadWriteTimeout = XML_TIMEOUT;
            //Dal.DatabaseAbstractionLayer dal = new Dal.DatabaseAbstractionLayer("");
            //request.Headers[HttpRequestHeader.IfNoneMatch] = dal.GetEtag(uri);
            //request.IfModifiedSince = dal.GetLastDownloadDate(uri);
            HttpWebResponse res;
            try
            {
                using ( res = (HttpWebResponse)request.GetResponse())
                {
                    if (res.StatusCode == HttpStatusCode.NotModified)
                        throw new WebException("Content Not Modified");
                    return res.ContentType.ToLower().Contains("xml");
                }
            }
            catch (WebException e)
            {
                if (e.Response != null)
                    if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
                        throw new WebException("Content Not Modified");
                Console.WriteLine("IsXml check : " + uri.ToString() + " " + e.Message);
  
                
                request = MakeRequestObject(uri);
                //Dont wanna wait more than 5 secs to see if this is XML.
                request.Timeout = XML_TIMEOUT;
                request.ReadWriteTimeout = XML_TIMEOUT;
                try
                {
                    using ( res = (HttpWebResponse)request.GetResponse())
                    {

                        return res.ContentType.ToLower().Contains("xml");
                     
                        
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ISXML : Unable to get Page with HEAD or GET : " + ex.Message);
                    return false;
                }
            }
        }

        public static HttpWebRequest MakeRequestObject(Uri uri)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
           
            request.ReadWriteTimeout = 5000;
            request.Timeout = 5000;
            request.KeepAlive = true;
            request.Pipelined = true;
            request.AllowAutoRedirect = false;
            //request.ContentType = "text/html";
            //request.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Anonymous;
            request.Method = "GET";
            request.ServicePoint.ConnectionLimit = 200;
            //request.IfModifiedSince = DateTime.Now.Subtract(new TimeSpan(24, 1, 0));
            return request;
        }
		        
  

    }
}
